/**
 *******************************************************************************
 * \brief   CAS EBX Project Work "Kaffeemaschine"
 *
 * \file    grounds.c
 * \version 1.0
 * \date    30.06.2010
 * \author  Baehler Thomas, Liechti Beat, Sauter Marc
 * \author  Vuksic Valentina, Zbinden Rene
 *
 * \remark  Last Modifications:
 * \remark  V1.0, 30.06.2010   Initial release
 *******************************************************************************
 **/

/*
 *******************************************************************************
 * Definitions
 *******************************************************************************
 */
/** \brief The grounds sensor delivers a value of 1, when grounds is removed. */
#define GROUNDS_REMOVED 1


/*
 *******************************************************************************
 * Imports
 *******************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <unistd.h>

#include "coffee2.h"
#include "channel.h"
#include "pool.h"
#include "device.h"

/*
 *******************************************************************************
 * Local Variables
 *******************************************************************************
 */
static tChannel *c14, /**c16, *c17,*/ *c35;
static tPool *p2, *p3;
static tDevice *d16, *d17;
static int timeExpired;


/*
 *******************************************************************************
 * Local Function Declaration
 *******************************************************************************
 */
static void sigtermHandler(int signal);
static void setTimeExpired(int signal);


/**
 *******************************************************************************
 * setTimeExpired
 *
 * \brief handle SIGALRM signal, set timeExpired
 *
 *******************************************************************************
 **/
static void setTimeExpired(int signal) {
	timeExpired = 1;
	return;
}


/**
 *******************************************************************************
 * sigtermHandler
 *
 * \brief handle SIGTERM signal, close all pools and channels and exit
 *
 *******************************************************************************
 **/
static void sigtermHandler(int signal) {
	syslog(LOG_INFO, "SIGTERM reveiced, stopping ...");
	/* open channels and pools */
	//closeChannel(c16);
	//closeChannel(c17);
	closeDevice(d16);
	closeDevice(d17);
	closeChannel(c35);

	closePool(p2);
	closePool(p3);
	/* close syslog */
	closelog();
	/* close and remove the runfile */
	exit(EXIT_SUCCESS);
}


/**
 *******************************************************************************
 * mainGrounds
 *
 * \brief Activity: "Filterkuchen"
 *
 * \return pid
 *
 *******************************************************************************
 **/
pid_t mainGrounds(){
	pid_t pid;
	sigset_t sigmask;
	struct sigaction sigtermAction;
	enum e_errors error = NO_ERROR;
	int order = 0;
	int parameter = 0;
	int activate = 1;
	int groundsensor = 0;

	pid = fork();
	if (pid == 0) {
		/* syslog */
		openlog("coffee-grounds", LOG_PID, LOG_DAEMON);
		/* block all signals other than SIGTERM */
		sigemptyset(&sigmask);
		sigaddset(&sigmask, SIGTERM);
		sigtermAction.sa_handler = sigtermHandler;
		sigtermAction.sa_mask = sigmask;
		if (sigaction(SIGTERM, &sigtermAction, NULL) == -1){
			syslog(LOG_ERR, "unable to setup signal handling!");
		}
		/* register alarm function */
		if (signal(SIGALRM, setTimeExpired) == SIG_ERR) {
			syslog(LOG_ERR, "can't register SIGALRM!");
		}
		/* open channels and pools */
		c14 = openChannelRead("C14", sizeof(int));  /* read from "Milk" */
		//c16 = openChannelRead("C16", sizeof(int));  /* read from
		//												"Kuchensensor" */
		//c17 = openChannelWrite("C17", sizeof(int)); /* write to
		//												"Kuchenauswerfer" */
		d16 = openDeviceRead("/dev/c2cakemtr");
		d17 = openDeviceWrite("/dev/c2cakermv");
		c35 = openChannelWrite("C35", sizeof(int)); /* write to
														"User Interface" */
		p2 = openPool("P2", sizeof(parameter));     /* "Parameter" */
		p3 = openPool("P3", sizeof(error));         /* "Error" */

		while (1) {
			if (readChannel(c14, &order) > 0) {
				syslog(LOG_INFO, "order from C14 received");
				/* read the parameter */
				readFromPool(p2, &parameter);
				/* start the milk pump */
				syslog(LOG_INFO, "activating grounds remover");
				//writeChannel(c17, &activate);
				writeDevice(d17, activate);
				usleep(100); /* no need to hurry */
				alarm(WAIT_FOR_GROUNDS_TIMEOUT);
				//readChannel(c16, & groundsensor);
				readDevice(d16, &groundsensor);
				while (groundsensor < GROUNDS_REMOVED && timeExpired == 0) {
					usleep(500);
					//readChannel(c16, & groundsensor);
					readDevice(d16, &groundsensor);
				}
				alarm(0);
				if (timeExpired == 1){
					syslog(LOG_ERR, "grounds system defective");
					error = GROUNDS_TIMEOUT;
					/*water pump seems to be defective ... */
					writeToPool(p3, &error);
				}
				syslog(LOG_INFO, "sending order to C35, LAST MESSAGE");
				writeChannel(c35, &order);
			}
			usleep(500);
		}
	}
	return pid;
}
